package com.gaga.console.core.service.impl;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gaga.common.enums.DelFlag;
import com.gaga.common.enums.Enabled;
import com.gaga.common.result.Result;
import com.gaga.common.utils.AESUtils;
import com.gaga.common.utils.AesAiobsUtils;
import com.gaga.console.base.entity.PageParams;
import com.gaga.console.base.entity.SecretKeyLoginBody;
import com.gaga.console.base.mybatisplus.LambdaQueryWrapperExt;
import com.gaga.console.base.service.impl.SuperServiceImpl;
import com.gaga.console.core.entity.SysUser;
import com.gaga.console.core.entity.SysUserRole;
import com.gaga.console.core.entity.dto.SecretKeyDto;
import com.gaga.console.core.entity.dto.SecretThridDto;
import com.gaga.console.core.entity.result.SecretThridResult;
import com.gaga.console.core.entity.vo.SysUserVO;
import com.gaga.console.core.mapper.SysUserMapper;
import com.gaga.console.core.service.SysRoleMenuService;
import com.gaga.console.core.service.SysUserRoleService;
import com.gaga.console.core.service.SysUserService;
import com.gaga.metadata.common.assertion.Asserts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liujia
 * @since 2022-05-19
 */
@Service
public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser> implements SysUserService {


    @Autowired
    private SysRoleMenuService sysRoleMenuService;

    @Autowired
    private SysUserRoleService sysUserRoleService;


    @Override
    public Result login(String username, String password) {
        SysUser user = getUserByUsername(username);
        if (Asserts.isNull(user)) {
            return Result.fail("账号或密码错误");
        }
        String userPassword = user.getPassword();
        if (Asserts.isNullString(password)) {
            return Result.fail("密码不能为空");
        }
        if (Asserts.isEquals(password, userPassword)) {
            if (user.getEnabled().intValue() == Enabled.DISABLE.getCode()) {
                return Result.fail("账号已被禁用");
            }
            StpUtil.login(user.getId());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return Result.ok(tokenInfo, "登录成功");
        } else {
            return Result.fail("账号或密码错误");
        }
    }

    @Override
    public Result getUserInfo() {
        SysUser user = getById(StpUtil.getLoginIdAsInt());

        SysUserVO sysUserVo = new SysUserVO();
        BeanUtil.copyProperties(user, sysUserVo);
        if (user != null) {
            HashSet<String> permissionList = this.permissionList();
            sysUserVo.setPermissions(permissionList);
        }
        return Result.ok(sysUserVo);
    }

    @Override
    public HashSet<String> getPermissionList() {
        return this.permissionList();
    }

    @Override
    public boolean customSave(SysUser entity) {
        this.saveOrUpdate(entity);
        if (entity.getRoleIdList() != null && entity.getRoleIdList().size() > 0 && entity.getId() != null) {
            List<SysUserRole> collect = entity.getRoleIdList().stream().map(s -> {
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setRoleId(Long.valueOf(s));
                sysUserRole.setUserId(entity.getId());
                return sysUserRole;
            }).collect(Collectors.toList());
            //先删除后增加
            sysUserRoleService.remove(Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getUserId, entity.getId()));
            // 重新写入角色对应的权限值
            sysUserRoleService.saveBatch(collect);
        }
        return Boolean.TRUE;
    }

    @Override
    public IPage<SysUser> customPageList(PageParams<SysUser> data) {
        LambdaQueryWrapperExt<SysUser> wraps = new LambdaQueryWrapperExt<>();
        wraps.eq(SysUser::getDelFlag, DelFlag.OK.getCode());
        data.buildSpecWrap(wraps);

        IPage<SysUser> roleIPage = this.page(data.buildPage(), wraps);

        roleIPage.getRecords().forEach(sysUser -> {
            List<Long> roleIdList = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, sysUser.getId())).stream().map(sysUserRole -> sysUserRole.getRoleId()).collect(Collectors.toList());
            sysUser.setRoleIdList(roleIdList);
        });

        return roleIPage;
    }

    @Override
    public Result loginBySecretKey(SecretKeyLoginBody secretKeyLoginBody) {
        if (Asserts.isNullString(secretKeyLoginBody.getSecretKey())) {
            return Result.fail("秘钥不能为空");
        }
        return thridSecretKeyHandler(secretKeyLoginBody);
    }

    /**
     * 第三方
     *
     * @param secretKeyLoginBody
     * @return
     */
    private Result thridSecretKeyHandler(SecretKeyLoginBody secretKeyLoginBody) {
        SecretThridResult secretThridResult = postVerify(secretKeyLoginBody);

        if (secretThridResult.getCode() == 401) {
            return Result.fail("秘钥不合法");
        }
        if (secretThridResult.getCode() == 200) {
            // 检查密钥是否过期
            if (secretThridResult.getData() != null && secretThridResult.getData().getExpireTime() != null) {
                if (secretThridResult.getData().getExpireTime().before(new Date())) {
                    return Result.fail("秘钥已过期，到期时间" + DateUtil.format(secretThridResult.getData().getExpireTime(), "yyyy-MM-dd HH:mm:ss"));
                }
            }
            StpUtil.login(secretThridResult.getData().getActiveCode());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return Result.ok(tokenInfo, "登录成功");
        } else {
            return Result.fail(secretThridResult.getMsg());
        }
    }

    /**
     * 自己做的加密 后续要放弃掉
     *
     * @param secretKeyLoginBody
     * @return
     */
    private Result innerSecretKeyHandler(SecretKeyLoginBody secretKeyLoginBody) {
        try {
            String decrypt = AESUtils.decrypt(secretKeyLoginBody.getSecretKey());
            SecretKeyDto secretKeyDto = JSON.parseObject(decrypt, SecretKeyDto.class);
            Date currDate = new Date();
            if (secretKeyDto.getEndDate().before(currDate)) {
                return Result.fail("秘钥已过期");
            }
            StpUtil.login(secretKeyDto.getSeccretKey());
            SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
            return Result.ok(tokenInfo, "登录成功");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("秘钥错误");
        }
    }

    @Override
    public Result getSecretKeyInfo(SecretKeyLoginBody secretKeyLoginBody) {
        if (Asserts.isNullString(secretKeyLoginBody.getSecretKey())) {
            return Result.fail("秘钥不能为空");
        }
        try {
            SecretThridResult secretThridResult = postVerify(secretKeyLoginBody);
            if (secretThridResult.getCode() == 401) {
                return Result.fail("秘钥不合法");
            }

            return Result.ok(secretThridResult);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.fail("秘钥错误");
        }
    }

    private SecretThridResult postVerify(SecretKeyLoginBody secretKeyLoginBody) {
        SecretThridDto secretThridDto = new SecretThridDto();
        secretThridDto.setAppKey(AesAiobsUtils.APP_KEY);
        try {
            secretThridDto.setActiveCode(AesAiobsUtils.encrypt(secretKeyLoginBody.getSecretKey()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        String result = HttpUtil.post(AesAiobsUtils.verifyUrl, JSON.toJSONString(secretThridDto), 10000);

        SecretThridResult secretThridResult = JSON.parseObject(result, SecretThridResult.class);
        return secretThridResult;
    }

    private HashSet<String> permissionList() {
        List<String> roleList = StpUtil.getRoleList();
        HashSet<String> permissionSet = new HashSet<>();
        if (roleList != null && roleList.size() > 0) {
            roleList.forEach(roleId -> {
                permissionSet.addAll(sysRoleMenuService.getMenuIdByRoleId(Long.valueOf(roleId)));
            });
        }
        return permissionSet;
    }


    public SysUser getUserByUsername(String username) {
        SysUser user = getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username).eq(SysUser::getDelFlag, 0));
        return user;
    }
}
